﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using TinyLib.Input;
using TinyLib.Sprite;
using TinyLib.Entity;
using TinyLib.Collision;

using GodBuilderIdea.Tools;

namespace GodBuilderIdea
{
    public class EntityManager : Entity
    {
        List<WorldEventBox> m_world_events;
        TileBoard m_tiles;
        List<Player> m_players;
        List<Button> m_tool_btns;

        MouseState m_State;
        MouseState m_StateOld;
        CollisionManager coll_manager;
        PlayerMenu player_menu; //one item that is same for all players (and then you switch who's turn it is)

        Sprite end_of_game_board;
        Sprite hover_tile;
        Player playerA, playerB, NPC;
        Player active_player;
        int active_index = 0;
        int m_turns = 16;
        int m_turns_originally = 16;
        int m_turn_prev_event = 16;

        int weBoxIndex = 0;

        SpriteFont m_dbg_font, m_large_font;
        bool m_end_of_game = false;
        bool m_start_sequence = true;
        bool have_spawned_tribes = false;
        bool m_handle_lava = false;
        bool m_change_player = false;
        int lava_wave = 1;
        bool m_can_place_tribe = false;
        bool m_tribe_selected = false;
        bool m_updating_world = false; 

        float npc_timer = 0;
        float npc_timer_counter = 1000;

        String m_new_turn_text = "Player A's turn";

        Sprite m_current_pointer, m_paint_pointer, m_bucket_pointer, m_tribe_pointer, m_can_place_tribe_marker, m_can_not_place_tribe_marker;

        public EntityManager(Game game, SpriteBatch sprite_batch)
            : base(game, sprite_batch)
        {
            Initialize();
            //active_player.m_currentTool = new DrawTool(m_tiles.Tiles);
            coll_manager = new CollisionManager();
        }

        public override void Initialize()
        {
            Random rand = new Random();
            m_dbg_font = Game.Content.Load<SpriteFont>("Font");
            m_large_font = Game.Content.Load<SpriteFont>("LargeFont");

            m_tiles = new TileBoard(new List<EnvTile>(), 20, 10);
 
            for (int x = 0; x < m_tiles.Width; x++)
            {
                for (int y = 0; y < m_tiles.Height; y++)
                {
                    EnvTile tile = new EnvTile(Game, Spritebatch);
                    tile.Initialize();
                    tile.Position = new Vector2(x * tile.texture2D.Width + 100, y * tile.texture2D.Height + 100);

                    if (x == 0)
                    { tile.left = true; }
                    else if (x == m_tiles.Width-1)
                    { tile.right = true; }
                    if (y == 0)
                    { tile.top = true; }
                    if (y == m_tiles.Height-1)
                    { tile.bottom = true; }

                    m_tiles.Tiles.Add(tile);
                }
            }

            int cheat_pwr = rand.Next(1, 4);

            playerA = new Player(Game, Spritebatch, "PlayerA");
            playerA.position = new Vector2(200, 800);
            playerA.m_active = true;
            playerA.m_goal.m_player_name = "Player A";
            playerA.m_goal.show_obscured = true;
            playerA.player_gui.color = Color.Red;
            playerA.m_tribe_type = Tribe.TribeType.WARM;
            playerA.m_currentTool = new DrawTool(m_tiles, EnvTile.EnvironmentType.GRASS);

            if (cheat_pwr <= 2)
            { playerA.m_cheat_power = true; }

            playerB = new Player(Game, Spritebatch, "PlayerB");
            playerB.position = new Vector2(400, 800);
            playerB.m_goal.m_player_name = "Player B";
            playerB.player_gui.color = Color.LightBlue;
            playerB.m_currentTool = new DrawTool(m_tiles, EnvTile.EnvironmentType.GRASS);
            playerB.m_tribe_type = Tribe.TribeType.COLD;
            if (cheat_pwr >= 3)
            { playerB.m_cheat_power = true; }

            NPC = new Player(Game, Spritebatch, "NPC");
            NPC.position = new Vector2(600, 800);
            NPC.m_goal.m_player_name = "NPC";
            NPC.player_gui.color = Color.Blue;
            NPC.m_currentTool = new DrawTool(m_tiles, EnvTile.EnvironmentType.GRASS);
            NPC.m_tribe_type = Tribe.TribeType.SEA;

            m_players = new List<Player>();
            m_players.Add(playerA);
            m_players.Add(playerB);
            m_players.Add(NPC);
            active_player = playerA;

            AssignGoals();

            InitializeGUI();

            InitializeWorldEvents();
        }

        public void InitializeGUI()
        {
            player_menu = new PlayerMenu(Game, Spritebatch);
            player_menu.Initialize();

            Texture2D tex = Game.Content.Load<Texture2D>("images/end_of_game_board");
            end_of_game_board = new Sprite(Spritebatch, tex, Game);
            end_of_game_board.position = new Vector2(50, 20);

            tex = Game.Content.Load<Texture2D>("images/bucket_pointer");
            m_bucket_pointer = new Sprite(Spritebatch, tex, Game);

            tex = Game.Content.Load<Texture2D>("images/painting_pointer");
            m_paint_pointer = new Sprite(Spritebatch, tex, Game);

            tex = Game.Content.Load<Texture2D>("images/move_tribe_pointer");
            m_tribe_pointer = new Sprite(Spritebatch, tex, Game);

            m_current_pointer = m_paint_pointer;

            m_tool_btns = new List<Button>();
            Button btn = new Button(Game, Spritebatch, Button.ButtonType.PAINT);
            btn.m_pressed = true;
            m_tool_btns.Add(btn);
            btn = new Button(Game, Spritebatch, Button.ButtonType.BUCKET);
            btn.AnimatedSprite.position = new Vector2(m_tool_btns[0].AnimatedSprite.position.X + 65, m_tool_btns[0].AnimatedSprite.position.Y);
            btn.Enabled = false;
            m_tool_btns.Add(btn);
            btn = new Button(Game, Spritebatch, Button.ButtonType.MOVE);
            btn.AnimatedSprite.position = new Vector2(m_tool_btns[0].AnimatedSprite.position.X + 130, m_tool_btns[0].AnimatedSprite.position.Y);
            btn.Enabled = false;
            
            m_tool_btns.Add(btn);
            btn = new Button(Game, Spritebatch, Button.ButtonType.NEXT);
            btn.AnimatedSprite.position = new Vector2(m_tool_btns[0].AnimatedSprite.position.X + 65, m_tool_btns[0].AnimatedSprite.position.Y - 65);            
            m_tool_btns.Add(btn);

            tex = Game.Content.Load<Texture2D>("images/tile_hover");
            hover_tile = new Sprite(Spritebatch, tex, Game);

            tex = Game.Content.Load<Texture2D>("images/tile_hover_can_place");
            m_can_place_tribe_marker = new Sprite(Spritebatch, tex, Game);

            tex = Game.Content.Load<Texture2D>("images/tile_hover_can_not_place");
            m_can_not_place_tribe_marker = new Sprite(Spritebatch, tex, Game);
        }

        public void InitializeWorldEvents()
        {
            m_world_events = new List<WorldEventBox>();
            WorldEventBox weBox = new WorldEventBox(Game, Spritebatch, "You are three gods who are creating a world together.\nWhen your world have evolved enough, you \nwill each have one tribe to look after.\nMake sure you collaborate! \n\nPress [Space] to continue.");
            weBox.m_active = true;
            weBox.ActivateEvent();
            m_world_events.Add(weBox); //0

            weBox = new WorldEventBox(Game, Spritebatch, "You need to collaborate to cover your gray world with \nsomething else.\nThat will open up for tribes to move into your world! \nLeft-click on an environment type to the right, \nand then click on the tiles on the board.\nPress [Space] to continue.");
            weBox.m_active = false;
            m_world_events.Add(weBox); //1

            weBox = new WorldEventBox(Game, Spritebatch, "...that the surrounding tiles affect the ones you \nplace? Try for example to put a sand tile in an area \nof water tiles!\n\nPress [Space] to continue.", true);
            weBox.m_active = false;
            m_world_events.Add(weBox); //2

            weBox = new WorldEventBox(Game, Spritebatch, "You can now use the [Bucket Tool] (hotkey: [S]).\nYou can use the [Bucket Tool] to fill an entire area\nof one environment type with another type.\n\nPress [Space] to continue.", true);
            weBox.m_active = false;
            weBox.RegisterActionEvent(new ActionEvent(m_tool_btns[1].Enable));
            m_world_events.Add(weBox); //3

            weBox = new WorldEventBox(Game, Spritebatch, "Now that you have created the world, tribes have \nmoved in. You each have one tribe of your own. \n\nPress [Space] to continue.");
            weBox.m_active = false;
            m_world_events.Add(weBox); //4

            weBox = new WorldEventBox(Game, Spritebatch, "...that some types of environment can harm your \ntribes, and other can make them prosper and \nmultiply?\nTry out what happens!\n\nPress [Space] to continue.", true);
            weBox.m_active = false;
            m_world_events.Add(weBox); //5

            weBox = new WorldEventBox(Game, Spritebatch, "You can now also move your tribes.\nYou move them by selecting the [Tribe Tool]\n(hotkey: [D]). When the tool is selected, you\nclick on a tribe and then a destination tile.\nThe destination tile has to be within 2 tiles of the\ntribes current tile.\nPress [Space] to continue.");
            weBox.m_active = false;
            weBox.RegisterActionEvent(new ActionEvent(m_tool_btns[2].Enable));
            m_world_events.Add(weBox); //6

            weBox = new WorldEventBox(Game, Spritebatch, "Oh no! The middle of the map is a volcano.\nThe tribes will die if they come in contact \nwith the lava. \n\nPress [Space] to continue.");
            weBox.m_active = false;
            m_world_events.Add(weBox); //7
        }
        void AssignGoals()
        {
            List<Goal.GoalType> goals = new List<Goal.GoalType>();

            for (int i = 0; i < (int)Goal.GoalType.SIZE; i++)
            {
                Goal.GoalType goal_type = (Goal.GoalType)i;
                goals.Add(goal_type);
            }

            Random rand = new Random();
            Goal.GoalType rand_goal_type;

            foreach (Player p in m_players)
            {
                int r = rand.Next(0, goals.Count);
                rand_goal_type = (Goal.GoalType)r;
                p.m_goal.Initialize(rand_goal_type);
                p.m_goal.m_cheat_power = p.m_cheat_power;

                foreach (Goal.GoalType g in goals)
                {
                    if (g == (Goal.GoalType)r)
                    {
                        goals.Remove(g);
                        break;
                    }
                }
                
            }
        }

        void StartSequence(ref InputManager inputManager)
        {
            if (inputManager.bJustPressed(Keys.Enter))
            {
                if (playerA.m_goal.show_obscured)
                {
                    playerA.m_goal.show_obscured = false;
                    playerA.m_goal.show_initially = true;
                }
                else if (playerA.m_goal.show_initially)
                {
                    playerA.m_goal.show_initially = false;
                    playerB.m_goal.show_obscured = true;
                }
                else if (playerB.m_goal.show_obscured)
                {
                    playerB.m_goal.show_obscured = false;
                    playerB.m_goal.show_initially = true;
                }
                else if (playerB.m_goal.show_initially)
                {
                    playerB.m_goal.show_initially = false;
                    m_start_sequence = false;
                }
            }
        }

        public void HandleInput(ref InputManager inputManager)
        {
            if (m_start_sequence)
            {
                StartSequence(ref inputManager);
            }

            if(active_player.m_cheat_power)
            {
                if (inputManager.bIsDown(Keys.C) && !active_player.m_cheat_have_cheated_this_turn)
                {
                    active_player.m_cheat_tribes_to_be_deployed++;
                    active_player.m_cheat_have_cheated_this_turn = true;
                }
            }

            if (inputManager.bJustPressed(Keys.Space))
            {
                foreach (WorldEventBox w in m_world_events)
                {
                    if (w.m_active)
                    {
                        weBoxIndex++;
                        w.m_active = false;
                    }
                }
            }
            if (inputManager.bJustPressed(Keys.A) &&
                m_tool_btns[0].Enabled)
            {
                active_player.m_currentTool = new DrawTool(m_tiles, active_player.m_currentTool.m_tileType);
                m_current_pointer = m_paint_pointer;
                foreach (Button btn in m_tool_btns)
                {
                    if (btn.m_type == Button.ButtonType.PAINT)
                    { btn.m_pressed = true; }
                    else
                    { btn.m_pressed = false; }
                }
            }
            if (inputManager.bJustPressed(Keys.S) &&
                m_tool_btns[1].Enabled)
            {
                active_player.m_currentTool = new BucketTool(m_tiles, active_player.m_currentTool.m_tileType);
                m_current_pointer = m_bucket_pointer;
                foreach (Button btn in m_tool_btns)
                {
                    if (btn.m_type == Button.ButtonType.BUCKET)
                    { btn.m_pressed = true; }
                    else
                    { btn.m_pressed = false; }
                }
            }
            if (inputManager.bJustPressed(Keys.D) &&
                m_tool_btns[2].Enabled)
            {
                active_player.m_currentTool = new MoveTribeTool(active_player, m_players, m_tiles.Tiles);
                m_current_pointer = m_tribe_pointer;
                foreach (Button btn in m_tool_btns)
                {
                    if (btn.m_type == Button.ButtonType.MOVE)
                    { btn.m_pressed = true; }
                    else
                    { btn.m_pressed = false; }
                }
            }

            m_StateOld = m_State;
            m_State = Mouse.GetState();

            int x = (int)inputManager.mouseAbsolutePosition.X;
            int y = (int)inputManager.mouseAbsolutePosition.Y;

            m_current_pointer.position = new Vector2(x, y);
            
            foreach (EnvTile tile in m_tiles.Tiles)
            {
                if (tile.Rectangle.Contains(new Point(x,y)))
                { hover_tile.position = tile.position; break; }
            }
            

            if ((m_State.LeftButton == ButtonState.Pressed)) 
            {
                if ((m_StateOld.LeftButton != ButtonState.Pressed)) //just left clicked
                { MouseLeftClick(x, y, false); }
                else
                { MouseLeftClick(x, y, true); }
                
            }

            if ((m_State.RightButton == ButtonState.Pressed) && (m_StateOld.RightButton != ButtonState.Pressed)) //just right clicked
            {
                MouseRightClick(x, y);
            }
        }

        public void MouseRightClick(int x, int y)
        {
            active_player.m_currentTool.MouseRightClick(x, y);
        }

        #region unused function
        /// <summary>
        /// Updates all tiles based on the surrounding tiles.        
        /// </summary>
        /// <param name="index"></param>
        
        /*
        private void UpdateEnvMatrix(int index)
        {
            for (int tileIndex = 0; tileIndex < m_tiles.Tiles.Count; tileIndex++)
            {
                int[] numTiles = new int[((int)EnvTile.EnvironmentType.DEFAULT) + 1];
                EnvTile currentTile = m_tiles.Tiles[tileIndex];

                //Check N tile
                if ((tileIndex % m_tiles.Height) != 0)
                {
                    numTiles[(int)m_tiles.Tiles[tileIndex - 1].m_type]++;

                    //Check NW tile
                    if (((int)(tileIndex / m_tiles.Height)) != 0)
                    {
                        numTiles[(int)m_tiles.Tiles[tileIndex - 1 - m_tiles.Height].m_type]++;
                    }

                    //Check E tile
                    if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                    {
                        numTiles[(int)m_tiles.Tiles[tileIndex - 1 + m_tiles.Height].m_type]++;
                    }
                }

                //Check S tile
                if ((tileIndex % m_tiles.Height) != m_tiles.Height - 1)
                {
                    numTiles[(int)m_tiles.Tiles[tileIndex + 1].m_type]++;

                    //Check W tile
                    if (((int)(tileIndex / m_tiles.Height)) != 0)
                    {
                        numTiles[(int)m_tiles.Tiles[tileIndex + 1 - m_tiles.Height].m_type]++;
                    }

                    //Check E tile
                    if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                    {
                        numTiles[(int)m_tiles.Tiles[tileIndex + 1 + m_tiles.Height].m_type]++;
                    }
                }

                //Check W tile
                if (((int)(tileIndex / m_tiles.Height)) != 0)
                {
                    numTiles[(int)m_tiles.Tiles[tileIndex - m_tiles.Height].m_type]++;
                }

                //Check E tile
                if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                {
                    numTiles[(int)m_tiles.Tiles[tileIndex + m_tiles.Height].m_type]++;
                }


                //Get the highest number of envtile type surrounding current tile.
                int highestNumOfEnv = 0;
                int envIndex = -1;
                for (int i = 0; i < numTiles.Length; i++)
                {
                    if (numTiles[i] > highestNumOfEnv)
                    {
                        highestNumOfEnv = numTiles[i];
                        envIndex = i;
                    }
                }

                //Check to see if the surrounding tiles matches the current one.
                if (envIndex != -1 && envIndex != ((int)currentTile.m_type) &&
                    highestNumOfEnv > 3 &&
                    EnvTile.EnvironmentType.DEFAULT != (EnvTile.EnvironmentType)envIndex)
                {
                    //if not...do stuff!
                    EnvTile.EnvironmentType currentType = currentTile.m_type;

                    switch (currentTile.m_type)
                    {
                        case EnvTile.EnvironmentType.DESERT:
                            UpdateEnvMatrix((EnvTile.EnvironmentType)envIndex, currentTile);
                            break;

                        case EnvTile.EnvironmentType.FOREST:
                            break;

                        case EnvTile.EnvironmentType.GRASS:
                            UpdateGrassType((EnvTile.EnvironmentType)envIndex, currentTile);
                            break;

                        case EnvTile.EnvironmentType.LAVA:
                            break;

                        case EnvTile.EnvironmentType.MOUNTAIN:
                            break;

                        case EnvTile.EnvironmentType.SNOW:
                            UpdateSnowType((EnvTile.EnvironmentType)envIndex, currentTile);
                            break;

                        case EnvTile.EnvironmentType.SWAMP:
                            break;

                        case EnvTile.EnvironmentType.WATER:
                            UpdateWaterType((EnvTile.EnvironmentType)envIndex, currentTile);
                            break;

                        default:
                            break;
                    }

                    //Check if the tile changed type.
                    if (currentType != currentTile.m_type)
                    {
                        //Update N tile
                        if ((tileIndex % m_tiles.Width) != 0)
                        {
                            UpdateEnvMatrix(tileIndex - 1);

                            //Update NW tile
                            if (((int)(tileIndex / m_tiles.Height)) != 0)
                                UpdateEnvMatrix(tileIndex - 1 - m_tiles.Height);

                            //Update NE tile
                            if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                                UpdateEnvMatrix(tileIndex - 1 + m_tiles.Height);

                        }

                        //Update S tile
                        if ((tileIndex % m_tiles.Width) != m_tiles.Height - 1)
                        {
                            UpdateEnvMatrix(tileIndex + 1);

                            //Update W tile
                            if (((int)(tileIndex / m_tiles.Height)) != 0)
                                UpdateEnvMatrix(tileIndex + 1 - m_tiles.Height);


                            //Update E tile
                            if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                                UpdateEnvMatrix(tileIndex + 1 + m_tiles.Height);

                        }

                        //Update W tile
                        if (((int)(tileIndex / m_tiles.Height)) != 0)
                            UpdateEnvMatrix(tileIndex - m_tiles.Height);

                        //Update E tile
                        if (((int)(tileIndex / m_tiles.Height)) != m_tiles.Width - 1)
                            UpdateEnvMatrix(tileIndex + m_tiles.Height);
                    }
                }
            }
        }
        //*/
        #endregion
        
        
        public void MouseLeftClick(int x, int y, bool hold)
        {
            //if klicket är på någon tile:
            //ändra tilepropertyn, kan köra på random som default


            if (!hold)
            {
                foreach (Button btn in m_tool_btns)
                {
                    if (btn.Rectangle.Contains(new Point(x, y)))
                    {
                        btn.m_pressed = true;

                        if (!btn.Enabled)
                            return;

                        if (btn.m_type == Button.ButtonType.PAINT)
                        {
                            active_player.m_currentTool = new DrawTool(m_tiles, active_player.m_currentTool.m_tileType);
                            m_current_pointer = m_paint_pointer;
                        }
                        else if (btn.m_type == Button.ButtonType.BUCKET)
                        {
                            active_player.m_currentTool = new BucketTool(m_tiles, active_player.m_currentTool.m_tileType);
                            m_current_pointer = m_bucket_pointer;
                        }
                        else if (btn.m_type == Button.ButtonType.MOVE)
                        { 
                            active_player.m_currentTool = new MoveTribeTool(active_player, m_players, m_tiles.Tiles);
                            m_current_pointer = m_tribe_pointer;
                        }
                        else if (btn.m_type == Button.ButtonType.NEXT)
                        {
                            m_change_player = true;
                        }

                        foreach (Button b in m_tool_btns)
                        {
                            if (b != btn) { b.m_pressed = false; }
                        }
                    }
                }
            }

            //did we click on a specific menu item?
            MenuItem menuItem = player_menu.ClickCheck(x, y);

            switch (menuItem.m_type)
            {
                case ITEMTYPE.ENVIRONMENT:
                    active_player.m_currentTool.m_tileType = menuItem.m_tileType;
                    break;
                case ITEMTYPE.TOOL:
                    if (menuItem.m_buttonType == BUTTONTYPE.DRAW)
                    {
                        //If we selected current tool
                        if (active_player.m_currentTool is DrawTool)
                            return;

                        active_player.m_currentTool = new DrawTool(m_tiles, active_player.m_currentTool.m_tileType);
                        m_current_pointer = m_paint_pointer;
                    }
                    else if (menuItem.m_buttonType == BUTTONTYPE.BUCKET)
                    {
                        //If we selected current tool
                        if (active_player.m_currentTool is BucketTool)
                            return;

                        active_player.m_currentTool = new BucketTool(m_tiles, active_player.m_currentTool.m_tileType);
                        m_current_pointer = m_bucket_pointer;
                    }
                    else if (menuItem.m_buttonType == BUTTONTYPE.MOVETRIBE)
                    {
                        //If we selected current tool
                        if (active_player.m_currentTool is MoveTribeTool)
                            return;

                        active_player.m_currentTool = new MoveTribeTool(active_player, m_players, m_tiles.Tiles);
                    }
                    break;
                case ITEMTYPE.NULL: //Player didn't click on anything specific, or (!), she clicked on the board!
                    break;
            }

            if (menuItem.m_type == ITEMTYPE.ENVIRONMENT)
            {
                if (menuItem.m_tileType != EnvTile.EnvironmentType.DEFAULT && menuItem.m_tileType != EnvTile.EnvironmentType.NEXT)
                {
                    if (active_player.m_currentTool is MoveTribeTool)
                    {
                        active_player.m_currentTool = new DrawTool(m_tiles, menuItem.m_tileType);
                        m_current_pointer = m_paint_pointer;
                        m_tool_btns[0].m_pressed = true;
                        m_tool_btns[2].m_pressed = false;
                    }
                    else
                    {
                        active_player.m_currentTool.m_tileType = menuItem.m_tileType;
                    }
                }
                else if (menuItem.m_tileType == EnvTile.EnvironmentType.NEXT && !hold)
                {
                    m_change_player = true;
                    //ChangePlayer();
                }
            }

            active_player.m_currentTool.m_activePlayer = active_player;
            active_player.m_currentTool.MouseLeftClick(x, y);
            
        }

        public void ChangePlayer()
        {
            foreach (Tribe t in active_player.m_tribes)
            { t.m_selected = false; }

            active_index++;

            if (active_index == 3) { 
                active_index = 0; 
                m_turns--;
                foreach (Player p in m_players){
                    foreach (Tribe t in p.m_tribes)
                    { t.DoSomeActions( m_tiles.Tiles, m_players); }
                }
                if (m_handle_lava)
                { HandleLava(); }
            }

            active_player.m_active = false;
            active_player = m_players[active_index];
            active_player.m_active = true;
            active_player.m_actions = active_player.m_def_actions;
            active_player.m_cheat_have_cheated_this_turn = false;
            player_menu.Reset();

            //fix the gui to the appropriate tool and envtype for the active player here
            EnvTile.EnvironmentType env_type = active_player.m_currentTool.m_tileType;
            player_menu.SetPos(env_type);

            Button.ButtonType type = Button.ButtonType.PAINT;
            if (active_player.m_currentTool is BucketTool)
            { type = Button.ButtonType.BUCKET; }
            else if (active_player.m_currentTool is DrawTool)
            { type = Button.ButtonType.PAINT; }
            else if (active_player.m_currentTool is MoveTribeTool)
            { type = Button.ButtonType.MOVE; }

            foreach (Button btn in m_tool_btns)
            {
                if (btn.m_type == type)
                { btn.m_pressed = true; }
                else
                { btn.m_pressed = false; }
            }

            if (active_index == 2)
            {
                NPC.NpcDoTurn(m_tiles.Tiles, m_players, weBoxIndex);
                ChangePlayer();
            }

            //update current pointer

            if (active_player.m_currentTool is DrawTool)
            { m_current_pointer = m_paint_pointer; }
            else if (active_player.m_currentTool is BucketTool)
            { m_current_pointer = m_bucket_pointer; }
            else if (active_player.m_currentTool is MoveTribeTool)
            { m_current_pointer = m_tribe_pointer; }

            m_updating_world = false;
            DeployCheatTribes();
        }

        void DeployCheatTribes()
        {
            foreach (Player p in m_players)
            {
                if (p.m_cheat_power && p.m_cheat_tribes_to_be_deployed > 0)
                {
                    Random rand = new Random();
                    int roll = rand.Next(1, 8);
                    if (roll > 5)
                    {
                        p.m_cheat_tribes_to_be_deployed--;
                        roll = rand.Next(0, m_tiles.Tiles.Count);
                        Tribe newTribe = new Tribe(Game, Spritebatch, p.m_tribe_type, p.m_goal.m_player_name);
                        newTribe.position = m_tiles.Tiles[roll].position;
                        newTribe.m_tile_index_pos = roll;
                        p.m_tribes.Add(newTribe);
                    }
                }
            }
        }

        void HandleLava()
        {
            List<int> first_turn_idxs = new List<int>();
            first_turn_idxs.Add(94); first_turn_idxs.Add(104);

            List<int> second_turn_idxs = new List<int>();
            second_turn_idxs.Add(83); second_turn_idxs.Add(93); second_turn_idxs.Add(103);
            second_turn_idxs.Add(115); second_turn_idxs.Add(114); second_turn_idxs.Add(113);
            second_turn_idxs.Add(105); second_turn_idxs.Add(95); second_turn_idxs.Add(85);
            second_turn_idxs.Add(84);

            List<int> third_turn_idxs = new List<int>();
            third_turn_idxs.Add(72); third_turn_idxs.Add(123); third_turn_idxs.Add(116);
            third_turn_idxs.Add(82); third_turn_idxs.Add(124); third_turn_idxs.Add(106);
            third_turn_idxs.Add(92); third_turn_idxs.Add(125); third_turn_idxs.Add(96);
            third_turn_idxs.Add(102); third_turn_idxs.Add(126); third_turn_idxs.Add(86);
            third_turn_idxs.Add(112); third_turn_idxs.Add(127); third_turn_idxs.Add(76);
            third_turn_idxs.Add(122); third_turn_idxs.Add(117); third_turn_idxs.Add(75);
            third_turn_idxs.Add(73); third_turn_idxs.Add(74);

            List<int> fourth_turn_idxs = new List<int>();
            fourth_turn_idxs.Add(61); fourth_turn_idxs.Add(133); fourth_turn_idxs.Add(87);
            fourth_turn_idxs.Add(71); fourth_turn_idxs.Add(134); fourth_turn_idxs.Add(77);
            fourth_turn_idxs.Add(81); fourth_turn_idxs.Add(135); fourth_turn_idxs.Add(67);
            fourth_turn_idxs.Add(91); fourth_turn_idxs.Add(136); fourth_turn_idxs.Add(66);
            fourth_turn_idxs.Add(101); fourth_turn_idxs.Add(137); fourth_turn_idxs.Add(65);
            fourth_turn_idxs.Add(111); fourth_turn_idxs.Add(127); fourth_turn_idxs.Add(64);
            fourth_turn_idxs.Add(121); fourth_turn_idxs.Add(117); fourth_turn_idxs.Add(63);
            fourth_turn_idxs.Add(131); fourth_turn_idxs.Add(107); fourth_turn_idxs.Add(62);
            fourth_turn_idxs.Add(132); fourth_turn_idxs.Add(97);

            List<int> relevant_indexes = new List<int>();

            switch (lava_wave)
            {
                case 1:
                    relevant_indexes = first_turn_idxs;
                    break;
                case 2:
                    relevant_indexes = second_turn_idxs;
                    break;
                case 3:
                    relevant_indexes = third_turn_idxs;
                    break;
                case 4:
                    relevant_indexes = fourth_turn_idxs;
                    break;
                default:
                    break;
            }

            for (int i = 0; i < relevant_indexes.Count; i++)
            {
                m_tiles.Tiles[relevant_indexes[i]].ChangeType(EnvTile.EnvironmentType.LAVA);
                
            }

            lava_wave++;
        }

        public override void Update(GameTime gameTime)
        {
            if (m_start_sequence)
            {
            }

            if (m_change_player)
            {
                if (active_index == 1)
                {
                    npc_timer += gameTime.ElapsedGameTime.Milliseconds;
                    if (npc_timer >= npc_timer_counter)
                    {
                        m_updating_world = true;

                        if (npc_timer >= (npc_timer_counter * 2))
                        {
                            npc_timer = 0.0f;
                            m_change_player = false;
                            ChangePlayer();
                        }
                    }
                }
                else
                {
                    m_change_player = false;
                    ChangePlayer();
                }
            }

            foreach (Button btn in m_tool_btns)
            { btn.Update(gameTime); }

            HandleWorldEvents();
            //else
           // {
            int tribe_selected = 0;
                foreach (Player p in m_players)
                {
                    p.Update(gameTime);
                    foreach (Tribe t in p.m_tribes)
                    {
                        t.Update(gameTime);
                        if (t.m_selected)
                        {
                            m_tribe_selected = true;
                            tribe_selected = 1;
                        }
                        if (t.m_split)
                        {
                            //split it up
                            t.m_amount /= 2;

                            Tribe newTribe = new Tribe(Game, Spritebatch, t.m_type, p.m_goal.m_player_name);
                            if (t.m_tile_index_pos < m_tiles.Width * (m_tiles.Height / 2))
                            {
                                newTribe.m_tile_index_pos = (t.m_tile_index_pos + 1);
                            }
                            else
                            {
                                newTribe.m_tile_index_pos = (t.m_tile_index_pos - 1);
                            }
                            newTribe.position = m_tiles.Tiles[newTribe.m_tile_index_pos].position;
                            p.m_tribes.Add(newTribe);
                            t.m_split = false;
                            break;
                        }
                    }
                }
                if (tribe_selected == 0)
                {
                    m_tribe_selected = false;
                }

                foreach (EnvTile tile in m_tiles.Tiles)
                {
                    tile.Update(gameTime);
                }

                foreach (WorldEventBox w in m_world_events)
                {
                    w.Update(gameTime);
                }

                player_menu.Update(gameTime);
                base.Update(gameTime);

                if (m_turns < 0)
                {
                    //trigger end of game-events
                    m_end_of_game = true;
                    EndOfGame();
                }
           // }
        }

        public void SpawnTribes()
        {
            Tribe start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.WARM, playerA.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[7].position;
            start_tribe.m_tile_index_pos = 7;
            start_tribe.m_amount = 3;
            playerA.m_tribes.Add(start_tribe);
            start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.WARM, playerA.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[59].position;
            start_tribe.m_tile_index_pos = 59;
            start_tribe.m_amount = 3;
            playerA.m_tribes.Add(start_tribe);

            start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.COLD, playerB.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[60].position;
            start_tribe.m_tile_index_pos = 60;
            start_tribe.m_amount = 3;
            playerB.m_tribes.Add(start_tribe);
            start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.COLD, playerB.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[20].position;
            start_tribe.m_tile_index_pos = 20;
            start_tribe.m_amount = 3;
            playerB.m_tribes.Add(start_tribe);

            start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.SEA, NPC.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[160].position;
            start_tribe.m_tile_index_pos = 160;
            start_tribe.m_amount = 3;
            NPC.m_tribes.Add(start_tribe);
            start_tribe = new Tribe(Game, Spritebatch, Tribe.TribeType.SEA, NPC.m_goal.m_player_name);
            start_tribe.position = m_tiles.Tiles[193].position;
            start_tribe.m_tile_index_pos = 193;
            start_tribe.m_amount = 3;
            NPC.m_tribes.Add(start_tribe);
        }

        public void HandleWorldEvents() //to check conditions for progression
        {
            if (weBoxIndex == 1)
            {
                
                if (!playerA.m_goal.show_initially
                    && !playerA.m_goal.show_obscured
                    && !playerB.m_goal.show_initially
                    && !playerB.m_goal.show_obscured
                    )
                {
                    weBoxIndex = 1;
                    m_world_events[1].ActivateEvent();
                    m_turn_prev_event = m_turns;
                    //SpawnTribes();
                }
            }
            else if (weBoxIndex == 2)
            {
                if (m_turns < (m_turns_originally - 1))
                {
                    m_world_events[2].ActivateEvent();
                    m_turn_prev_event = m_turns;
                }
            }
            else if (weBoxIndex == 3)
            {
                if (m_turns < (m_turns_originally - 2))
                {
                    weBoxIndex = 2;
                    m_world_events[3].ActivateEvent();
                    m_turn_prev_event = m_turns;
                }
            }
            else if (weBoxIndex == 4)
            {
                int def = 0;
                foreach (EnvTile et in m_tiles.Tiles)
                {
                    if (et.m_type == EnvTile.EnvironmentType.DEFAULT)
                    { def = 1; break; }
                }

                if (def == 0 && !have_spawned_tribes)
                {
                    have_spawned_tribes = true;
                    SpawnTribes();
                    m_world_events[4].ActivateEvent();
                    m_turn_prev_event = m_turns;
                }
            }
            else if (weBoxIndex == 5)
            {
                if (m_turns <= (m_turn_prev_event - 1))
                {
                    m_world_events[5].ActivateEvent();
                    m_turn_prev_event = m_turns;
                }
            }
            else if (weBoxIndex == 6)
            {
                if (m_turns <= (m_turn_prev_event - 1))
                {
                    m_world_events[6].ActivateEvent();
                    m_turn_prev_event = m_turns;
                }
            }
            else if (weBoxIndex == 7)
            {
                if (m_turns <= 5)
                {
                    m_world_events[7].ActivateEvent();
                    m_handle_lava = true;
                    m_tiles.Tiles[((m_tiles.Height * m_tiles.Width) / 2) + (m_tiles.Height / 2)].ChangeType(EnvTile.EnvironmentType.LAVA);
                    m_tiles.Tiles[((m_tiles.Height * m_tiles.Width) / 2) + (m_tiles.Height / 2) + m_tiles.Height].ChangeType(EnvTile.EnvironmentType.LAVA);
                    m_tiles.Tiles[((m_tiles.Height * m_tiles.Width) / 2) + (m_tiles.Height / 2) - m_tiles.Height].ChangeType(EnvTile.EnvironmentType.LAVA);
                }
            }
        }

        public void EndOfGame()
        {
            //calculate winning conditions and present on the screen
            foreach (Player p in m_players)
            {
                p.m_goal.CalcVictoryCondition(m_players, m_tiles.Tiles);
            }
        }

        public override void Draw(GameTime gameTime)
        {
            //foreach (EnvTile tile in m_tiles.Tiles)
            for (int i=0; i < m_tiles.Tiles.Count; i++)
            {
               // tile.Draw(gameTime);
                m_tiles.Tiles[i].Draw(gameTime);
                Color c;
                if (m_tiles.Tiles[i].left)
                { c = Color.Yellow; }
                else if (m_tiles.Tiles[i].right)
                { c = Color.Green; }
                else if (m_tiles.Tiles[i].top)
                { c = Color.Blue; }
                else if (m_tiles.Tiles[i].bottom)
                { c = Color.Red; }
                else { c = Color.White; }


               // Spritebatch.DrawString(m_dbg_font, "" + i, m_tiles.Tiles[i].position, c);
            }

           // Spritebatch.DrawString(m_large_font, m_new_turn_text, new Vector2(300, 300), Color.AliceBlue);
            /*
            bool m_can_place_tribe = false;
            bool m_tribe_selected = false;
            */
            if (m_tribe_selected)
            {
                List<int> selected_adjacent = new List<int>();
                List<EnvTile> tiles = m_tiles.Tiles;
                Point mousePointer;
                MouseState mState = Mouse.GetState();
                mousePointer = new Point(mState.X, mState.Y);
                foreach (Tribe t in active_player.m_tribes)
                {
                    if (t.m_selected)
                    { selected_adjacent = t.GetTwoAdjacent(m_tiles.Tiles); break; }
                }
                bool can_place = false;

                foreach (int i in selected_adjacent)
                {
                    if (tiles[i].Rectangle.Contains(mousePointer) &&
                        tiles[i].m_type != EnvTile.EnvironmentType.MOUNTAIN
                        && active_player.m_currentTool is MoveTribeTool
                        )
                    {
                        can_place = true;
                        m_can_place_tribe_marker.position = tiles[i].position;
                        m_can_place_tribe_marker.Draw(gameTime);
                    }
                    
                }

                if (!can_place && active_player.m_currentTool is MoveTribeTool)
                {
                    //if (active_player.m_currentTool is MoveTribeTool)
                    //{
                        foreach (EnvTile tile in tiles)
                        {
                            if (tile.Rectangle.Contains(mousePointer))
                            {
                                m_can_not_place_tribe_marker.position = tile.position;
                                m_can_not_place_tribe_marker.Draw(gameTime);
                            }
                        }
                    //}
                }
                /*
                m_can_place_tribe; <-- muspekaren är över en adjacent
                m_can_not_place_tribe; <-- muspekaren är inte över en adjacent
                    */
            }
            else
            { hover_tile.Draw(gameTime); }

            player_menu.Draw(gameTime);

            playerA.Draw(gameTime);
            playerB.Draw(gameTime);
            NPC.Draw(gameTime);

            Spritebatch.DrawString(m_large_font, "Turns left: " + m_turns, new Vector2(400, 10), Color.White);

            

            foreach (WorldEventBox w in m_world_events)
            {
                w.Draw(gameTime);
            }

            foreach (Button btn in m_tool_btns)
            { 
                btn.Draw(gameTime); 
            }

            if (m_change_player && !m_updating_world)
            {
                Spritebatch.DrawString(m_large_font, "NPC doing turn...", new Vector2(550, 400), Color.Red);
            }
            else if (m_updating_world)
            {
                Spritebatch.DrawString(m_large_font, "Updating world...", new Vector2(550, 400), Color.Red);
            }
            else if (active_player.m_actions <= 0)
            {
                Spritebatch.DrawString(m_large_font, "You have no more available actions this turn.", new Vector2(150, 400), Color.Red);
            }

            if (m_end_of_game)
            {
                //draw some relevant stuff
                end_of_game_board.Draw(gameTime);
                Spritebatch.DrawString(m_dbg_font, "Player A: \nGoal: " + playerA.m_goal.m_goal_text + "\nSuccess:" + playerA.m_goal.m_success, new Vector2(400, 200), Color.White);
                Spritebatch.DrawString(m_dbg_font, "Player B: \nGoal: " + playerB.m_goal.m_goal_text + "\nSuccess:" + playerB.m_goal.m_success, new Vector2(400, 400), Color.White);
                Spritebatch.DrawString(m_dbg_font, "NPC: \nGoal: " + NPC.m_goal.m_goal_text + "\nSuccess:" + NPC.m_goal.m_success, new Vector2(400, 600), Color.White);

            }

            m_current_pointer.Draw(gameTime);

            base.Draw(gameTime);
        }
    }
}
